package com.hello.gen.service;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hello.common.core.constant.Constants;
import com.hello.common.core.constant.GenConstants;
import com.hello.common.core.exception.ServiceException;
import com.hello.common.core.text.CharsetKit;
import com.hello.common.core.utils.StringUtils;
import com.hello.common.security.utils.SecurityUtils;
import com.hello.gen.domain.GenTable;
import com.hello.gen.domain.GenTableColumn;
import com.hello.gen.mapper.GenTableColumnMapper;
import com.hello.gen.mapper.GenTableMapper;
import com.hello.gen.util.GenUtils;
import com.hello.gen.util.VelocityInitializer;
import com.hello.gen.util.VelocityUtils;
import com.hello.gen.util.FileMergeUtils;
import com.hello.gen.config.GenConfig;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.beans.factory.annotation.Autowired;

import lombok.RequiredArgsConstructor;
import java.util.Objects;

/**
 * 业务 服务层实现
 * 
 * @author hello
 */
@Service
@RequiredArgsConstructor
public class GenTableServiceImpl extends ServiceImpl<GenTableMapper, GenTable> implements IGenTableService
{
    private static final Logger log = LoggerFactory.getLogger(GenTableServiceImpl.class);

    private final GenTableMapper genTableMapper;

    private final GenTableColumnMapper genTableColumnMapper;
    
    private final GenConfig genConfig;

    @Autowired
    private JdbcTemplate jdbcTemplate;

    /**
     * 查询业务信息
     * 
     * @param id 业务ID
     * @return 业务信息
     */
    @Override
    public GenTable selectGenTableById(Long id)
    {
        GenTable genTable = genTableMapper.selectById(id);
        setTableFromOptions(genTable);
        return genTable;
    }

    /**
     * 查询业务列表
     * 
     * @param genTable 业务信息
     * @return 业务集合
     */
    @Override
    public List<GenTable> selectGenTableList(GenTable genTable)
    {
        return genTableMapper.selectGenTableList(genTable);
    }

    /**
     * 查询据库列表
     * 
     * @param genTable 业务信息
     * @return 数据库表集合
     */
    @Override
    public List<GenTable> selectDbTableList(GenTable genTable)
    {
        return genTableMapper.selectDbTableList(genTable);
    }

    /**
     * 查询据库列表
     * 
     * @param tableNames 表名称组
     * @return 数据库表集合
     */
    @Override
    public List<GenTable> selectDbTableListByNames(String[] tableNames)
    {
        return genTableMapper.selectDbTableListByNames(tableNames);
    }

    /**
     * 查询所有表信息
     * 
     * @return 表信息集合
     */
    @Override
    public List<GenTable> selectGenTableAll()
    {
        return genTableMapper.selectGenTableAll();
    }

    /**
     * 查询表名称业务信息
     * 
     * @param tableName 表名称
     * @return 业务信息
     */
    @Override
    public GenTable selectGenTableByName(String tableName)
    {
        GenTable genTable = genTableMapper.selectGenTableByName(tableName);
        if (genTable != null) {
            setTableFromOptions(genTable);
        }
        return genTable;
    }

    /**
     * 修改业务
     * 
     * @param genTable 业务信息
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateGenTable(GenTable genTable)
    {
        try {
            // 记录关键信息到日志
            log.info("======开始保存表信息======");
            log.info("表名: {}", genTable.getTableName());
            log.info("表注释: {}", genTable.getTableComment());
            log.info("生成类型: {}", genTable.getGenType());
            
            // 从params中获取合并模式
            String mergeMode = "未设置";
            if (genTable.getParams() != null && genTable.getParams().containsKey("mergeMode")) {
                mergeMode = genTable.getParams().get("mergeMode").toString();
            } else if (genTable.getMergeMode() != null) {
                mergeMode = genTable.getMergeMode();
            }
            log.info("合并模式: {}", mergeMode);
            
            // 记录表字段数量
            int columnsCount = genTable.getColumns() != null ? genTable.getColumns().size() : 0;
            log.info("表字段数量: {}", columnsCount);
            
            // 路径信息
            log.info("生成路径: {}", genTable.getGenPath());
            log.info("后端生成路径: {}", genTable.getBackendGenPath());
            log.info("前端生成路径: {}", genTable.getFrontendGenPath());
            
            // 保存params中的特定参数
            Map<String, Object> paramsMap = new HashMap<>();
            Map<String, Object> originalParams = genTable.getParams();
            
            // 记录上级菜单信息
            if (originalParams != null) {
                if (originalParams.containsKey(GenConstants.PARENT_MENU_ID)) {
                    String parentMenuId = originalParams.get(GenConstants.PARENT_MENU_ID).toString();
                    paramsMap.put(GenConstants.PARENT_MENU_ID, parentMenuId);
                    // 直接设置到表对象上
                    genTable.setParentMenuId(parentMenuId);
                    log.info("设置上级菜单ID: {}", parentMenuId);
                }
                
                if (originalParams.containsKey(GenConstants.PARENT_MENU_NAME)) {
                    String parentMenuName = originalParams.get(GenConstants.PARENT_MENU_NAME).toString();
                    paramsMap.put(GenConstants.PARENT_MENU_NAME, parentMenuName);
                    // 直接设置到表对象上
                    genTable.setParentMenuName(parentMenuName);
                    log.info("设置上级菜单名称: {}", parentMenuName);
                }
                
                // 合并模式
                if (originalParams.containsKey("mergeMode")) {
                    String mergeModeValue = originalParams.get("mergeMode").toString();
                    paramsMap.put("mergeMode", mergeModeValue);
                    // 直接设置到表对象上
                    genTable.setMergeMode(mergeModeValue);
                }
                
                // 树表相关设置
                if (GenConstants.TPL_TREE.equals(genTable.getTplCategory())) {
                    String[] treeFields = {GenConstants.TREE_CODE, GenConstants.TREE_PARENT_CODE, GenConstants.TREE_NAME};
                    for (String field : treeFields) {
                        if (originalParams.containsKey(field)) {
                            paramsMap.put(field, originalParams.get(field));
                        }
                    }
                }
            }
            
            // 使用JSONObject确保生成合法的JSON格式
            String options = JSON.toJSONString(paramsMap);
            genTable.setOptions(options);
            
            // 从options设置相关字段，确保parentMenuName等字段被正确设置
            setTableFromOptions(genTable);
            
            // 记录更新后的值
            log.info("从options设置后 - 上级菜单ID: {}", genTable.getParentMenuId());
            log.info("从options设置后 - 上级菜单名称: {}", genTable.getParentMenuName());
            
            // 保存原始params的副本，因为有些地方可能需要用到
            Map<String, Object> tempParams = genTable.getParams();
            
            // 使用自定义更新方法，避免使用MyBatis-Plus的通用方法可能导致的问题
            int row = genTableMapper.updateGenTable(genTable);
            
            // 恢复params，以便后续操作可能需要
            genTable.setParams(tempParams);
            
            if (row > 0 && genTable.getColumns() != null)
            {
                for (GenTableColumn cenTableColumn : genTable.getColumns())
                {
                    // 确保每个列的params属性为null，避免序列化问题
                    cenTableColumn.setParams(null);
                    genTableColumnMapper.updateById(cenTableColumn);
                }
            }
        }
        catch (Exception e) {
            log.error("更新业务表信息失败：", e);
            throw new ServiceException("更新业务表信息失败：" + e.getMessage());
        }
    }

    /**
     * 删除业务对象
     * 
     * @param tableIds 需要删除的数据ID
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteGenTableByIds(Long[] tableIds)
    {
        removeBatchByIds(Arrays.asList(tableIds));
        genTableColumnMapper.deleteGenTableColumnByIds(tableIds);
    }

    /**
     * 导入表结构
     * 
     * @param tableList 导入表列表
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void importGenTable(List<GenTable> tableList)
    {
        String operName = SecurityUtils.getUsername();
        try
        {
            // 获取并记录项目根路径
            String defaultPath = System.getProperty("user.dir");
            log.info("获取项目根路径: {}", defaultPath);
            log.info("操作系统: {}", System.getProperty("os.name"));
            log.info("开始导入{}个表", tableList.size());
            
            for (GenTable table : tableList)
            {
                String tableName = table.getTableName();
                log.info("正在导入表: {}", tableName);
                GenUtils.initTable(table, operName);
                
                // 确保使用GenUtils中设置的路径
                String genPath = table.getGenPath();
                String backendPath = table.getBackendGenPath();
                String frontendPath = table.getFrontendGenPath();
                
                // 如果路径为空，则设置默认值
                if (StringUtils.isEmpty(genPath)) {
                table.setGenPath(defaultPath);
                }
                if (StringUtils.isEmpty(backendPath)) {
                    table.setBackendGenPath(defaultPath + File.separator + "hello-modules" + File.separator + "hello-" + table.getModuleName());
                }
                if (StringUtils.isEmpty(frontendPath)) {
                    table.setFrontendGenPath(defaultPath + File.separator + "hello-ui");
                }
                
                // 直接设置合并模式为智能合并(1)
                table.setMergeMode("1");
                
                // 设置默认参数
                Map<String, Object> paramsMap = new HashMap<>();
                paramsMap.put("mergeMode", "1"); // 合并模式，使用1而不是true
                
                // 从注入的配置中获取默认上级菜单ID
                String parentMenuId = genConfig.getParentMenuId();
                if (StringUtils.isEmpty(parentMenuId)) {
                    parentMenuId = "1"; // 如果配置中没有设置，则使用默认值1
                }
                
                String parentMenuName = genConfig.getParentMenuName();
                if (StringUtils.isEmpty(parentMenuName)) {
                    parentMenuName = "系统管理"; // 如果配置中没有设置，则使用默认值
                }
                
                paramsMap.put(GenConstants.PARENT_MENU_ID, parentMenuId);
                paramsMap.put(GenConstants.PARENT_MENU_NAME, parentMenuName);
                
                // 保存到options
                String options = JSON.toJSONString(paramsMap);
                table.setOptions(options);
                
                // 同时保存到内存中的params
                table.setParams(paramsMap);
                
                log.info("为表[{}]设置生成路径: {}, 后端路径: {}, 前端路径: {}, 合并模式: 智能合并, 上级菜单: {}", 
                    tableName, table.getGenPath(), table.getBackendGenPath(), table.getFrontendGenPath(), parentMenuName);
                
                int row = genTableMapper.insert(table);
                if (row > 0)
                {
                    // 保存列信息
                    List<GenTableColumn> genTableColumns = genTableColumnMapper.selectDbTableColumnsByName(tableName);
                    log.info("表[{}]的列数量: {}", tableName, genTableColumns.size());
                    for (GenTableColumn column : genTableColumns)
                    {
                        GenUtils.initColumnField(column, table);
                        genTableColumnMapper.insert(column);
                    }
                    log.info("表[{}]及其列信息导入成功", tableName);
                }
            }
            log.info("所有表导入完成");
        }
        catch (Exception e)
        {
            log.error("导入表结构失败", e);
            throw new ServiceException("导入失败：" + e.getMessage());
        }
    }

    /**
     * 预览代码
     * 
     * @param tableId 表编号
     * @return 预览数据列表
     */
    @Override
    public Map<String, String> previewCode(Long tableId)
    {
        Map<String, String> dataMap = new LinkedHashMap<>();
        // 查询表信息
        GenTable table = genTableMapper.selectById(tableId);
        if (table == null) {
            throw new ServiceException("表信息不存在");
        }
        
        List<GenTableColumn> columns = genTableColumnMapper.selectGenTableColumnListByTableId(tableId);
        if (columns == null || columns.isEmpty()) {
            throw new ServiceException("表字段信息不存在");
        }
        table.setColumns(columns);
        
        // 设置主子表信息
        setSubTable(table);
        // 设置主键列信息
        setPkColumn(table);
        VelocityInitializer.initVelocity();

        VelocityContext context = VelocityUtils.prepareContext(table);

        // 获取模板列表
        List<String> templates = VelocityUtils.getTemplateList(table.getTplCategory());
        
        // 添加SQL文件的自定义名称
        Map<String, String> customTemplateNames = new HashMap<>();
        customTemplateNames.put("vm/sql/sql.vm", "菜单SQL（添加）");
        customTemplateNames.put("vm/sql/sql-delete.vm", "菜单SQL（删除）");
        
        for (String template : templates)
        {
            // 渲染模板
            StringWriter sw = new StringWriter();
            Template tpl = Velocity.getTemplate(template, Constants.UTF8);
            tpl.merge(context, sw);
            
            // 使用自定义名称或原始模板名
            String displayName = customTemplateNames.getOrDefault(template, template);
            dataMap.put(displayName, sw.toString());
        }
        return dataMap;
    }

    /**
     * 生成代码（下载方式）
     * 
     * @param tableName 表名称
     * @return 数据
     */
    @Override
    public byte[] downloadCode(String tableName)
    {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ZipOutputStream zip = new ZipOutputStream(outputStream);
        generatorCode(tableName, zip);
        IOUtils.closeQuietly(zip);
        return outputStream.toByteArray();
    }

    /**
     * 批量生成代码（下载方式）
     * 
     * @param tableNames 表数组
     * @return 数据
     */
    @Override
    public byte[] downloadCode(String[] tableNames)
    {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ZipOutputStream zip = new ZipOutputStream(outputStream);
        for (String tableName : tableNames)
        {
            generatorCode(tableName, zip);
        }
        IOUtils.closeQuietly(zip);
        return outputStream.toByteArray();
    }

    /**
     * 生成代码（自定义路径）
     * 
     * @param tableName 表名称
     * @param genPath 生成路径
     * @param codeType 代码类型：backend-后端代码，frontend-前端代码，不传-生成全部
     */
    @Override
    public void generatorCode(String tableName, String genPath, String codeType)
    {
        // 查询表信息
        GenTable table = genTableMapper.selectGenTableByName(tableName);
        if (table == null) {
            throw new ServiceException("表信息不存在");
        }
        
        // 使用表中存储的合并模式设置，默认为智能合并(1)
        boolean mergeMode = "1".equals(table.getMergeMode());
        
        generatorCode(tableName, genPath, codeType, mergeMode);
    }

    /**
     * 生成代码（自定义路径）
     * 
     * @param tableName 表名称
     * @param genPath 生成路径
     * @param codeType 代码类型：backend-后端代码，frontend-前端代码，不传-生成全部
     * @param mergeMode 是否启用文件合并模式，true-合并，false-覆盖
     */
    @Override
    public void generatorCode(String tableName, String genPath, String codeType, boolean mergeMode)
    {
        // 查询表信息
        GenTable table = genTableMapper.selectGenTableByName(tableName);
        if (table == null) {
            throw new ServiceException("表信息不存在");
        }
        
        List<GenTableColumn> columns = genTableColumnMapper.selectGenTableColumnListByTableId(table.getTableId());
        if (columns == null || columns.isEmpty()) {
            throw new ServiceException("表字段信息不存在");
        }
        table.setColumns(columns);
        
        // 设置主子表信息
        setSubTable(table);
        // 设置主键列信息
        setPkColumn(table);

        // 如果传入了自定义路径，使用传入的路径
        if (StringUtils.isNotEmpty(genPath)) {
            log.info("使用传入生成路径: {}", genPath);
            // 替换掉table中的genPath
            table.setGenPath(genPath);
        }

        VelocityInitializer.initVelocity();

        VelocityContext context = VelocityUtils.prepareContext(table);

        // 获取模板列表
        List<String> templates = VelocityUtils.getTemplateList(table.getTplCategory());
        
        // 排除SQL文件模板
        templates = templates.stream()
                .filter(template -> !template.contains("sql.vm"))
                .collect(Collectors.toList());
        
        log.info("生成代码，表名: {}, 排除SQL文件后的模板数量: {}", tableName, templates.size());
        
        // 根据代码类型筛选模板
        if (StringUtils.isNotEmpty(codeType)) {
            log.info("根据代码类型筛选模板: {}", codeType);
            templates = filterTemplatesByCodeType(templates, codeType);
        }
        
        // 打印合并模式状态
        log.info("代码生成模式: {}", mergeMode ? "智能合并模式" : "覆盖模式");
        
        // 首先检查是否有文件已经存在
        List<String> existingFiles = new ArrayList<>();
        for (String template : templates) {
            try {
                String path = VelocityUtils.getGenPath(table, template);
                File file = new File(path);
                if (file.exists()) {
                    existingFiles.add(path);
                }
            } catch (Exception e) {
                log.error("检查文件是否存在时出错", e);
            }
        }
        
        // 如果有文件已存在，直接停止生成
        if (!existingFiles.isEmpty()) {
            log.info("发现{}个文件已存在，停止生成", existingFiles.size());
            throw new ServiceException(String.format("已有%d个文件存在，不再重复生成，包括: %s", 
                existingFiles.size(), 
                existingFiles.size() > 3 ? 
                    String.join(", ", existingFiles.subList(0, 3)) + "等..." : 
                    String.join(", ", existingFiles)));
        }
        
        // 所有文件都不存在，开始生成
        for (String template : templates) {
            // 渲染模板
            StringWriter sw = new StringWriter();
            Template tpl = Velocity.getTemplate(template, Constants.UTF8);
            tpl.merge(context, sw);
            try
            {
                String path = VelocityUtils.getGenPath(table, template);
                File file = new File(path);
                
                // 使用覆盖模式写入文件（因为已经确认文件不存在）
                log.info("生成代码到路径: {}", path);
                FileUtils.writeStringToFile(file, sw.toString(), CharsetKit.UTF_8);
            }
            catch (IOException e)
            {
                log.error("渲染模板失败，表名：{}，模板：{}", table.getTableName(), template, e);
                throw new ServiceException("渲染模板失败，表名：" + table.getTableName());
            }
        }
    }

    /**
     * 根据代码类型筛选模板
     * 
     * @param templates 模板列表
     * @param codeType 代码类型
     * @return 筛选后的模板列表
     */
    private List<String> filterTemplatesByCodeType(List<String> templates, String codeType) {
        List<String> filteredTemplates = new ArrayList<>();
        
        // 区分前后端的模板
        for (String template : templates) {
            // 后端模板通常包含.java.vm或.xml.vm
            boolean isBackendTemplate = template.contains(".java.vm") || template.contains(".xml.vm") 
                || template.contains(".sql.vm") || template.contains("mapper") || template.contains("pom.xml");
                
            // 前端模板通常包含.js.vm、.vue.vm或.html.vm
            boolean isFrontendTemplate = template.contains(".js.vm") || template.contains(".vue.vm") 
                || template.contains(".html.vm") || template.contains(".css.vm") || template.contains(".scss.vm")
                || template.contains("/api/");
                
            if ("backend".equals(codeType) && isBackendTemplate) {
                filteredTemplates.add(template);
            } else if ("frontend".equals(codeType) && isFrontendTemplate) {
                filteredTemplates.add(template);
            } else if (!"backend".equals(codeType) && !"frontend".equals(codeType)) {
                // 如果不是明确的前端或后端类型，则保留模板
                filteredTemplates.add(template);
            }
        }
        
        log.info("筛选模板结果: 原始模板数量={}, 筛选后模板数量={}", templates.size(), filteredTemplates.size());
        return filteredTemplates;
    }

    /**
     * 查询表信息并生成代码
     */
    private void generatorCode(String tableName, ZipOutputStream zip)
    {
        // 查询表信息
        GenTable table = genTableMapper.selectGenTableByName(tableName);
        if (table == null) {
            throw new ServiceException("表信息不存在");
        }
        // 生成代码到zip
        generatorCode(table, zip);
    }

    /**
     * 同步数据库
     * 
     * @param tableName 表名称
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void synchDb(String tableName)
    {
        GenTable table = genTableMapper.selectGenTableByName(tableName);
        List<GenTableColumn> tableColumns = table.getColumns();
        Map<String, GenTableColumn> tableColumnMap = tableColumns.stream().collect(Collectors.toMap(GenTableColumn::getColumnName, Function.identity()));

        List<GenTableColumn> dbTableColumns = genTableColumnMapper.selectDbTableColumnsByName(tableName);
        if (StringUtils.isEmpty(dbTableColumns))
        {
            throw new ServiceException("同步数据失败，原表结构不存在");
        }
        List<String> dbTableColumnNames = dbTableColumns.stream().map(GenTableColumn::getColumnName).collect(Collectors.toList());

        dbTableColumns.forEach(column -> {
            GenUtils.initColumnField(column, table);
            if (tableColumnMap.containsKey(column.getColumnName()))
            {
                GenTableColumn prevColumn = tableColumnMap.get(column.getColumnName());
                column.setColumnId(prevColumn.getColumnId());
                if (column.isList())
                {
                    // 如果是列表，继续保留查询方式/字典类型选项
                    column.setDictType(prevColumn.getDictType());
                    column.setQueryType(prevColumn.getQueryType());
                }
                if (StringUtils.isNotEmpty(prevColumn.getIsRequired()) && !column.isPk()
                        && (column.isInsert() || column.isEdit())
                        && ((column.isUsableColumn()) || (!column.isSuperColumn())))
                {
                    // 如果是(新增/修改&非主键/非忽略及父属性)，继续保留必填/显示类型选项
                    column.setIsRequired(prevColumn.getIsRequired());
                    column.setHtmlType(prevColumn.getHtmlType());
                }
                genTableColumnMapper.updateById(column);
            }
            else
            {
                genTableColumnMapper.insert(column);
            }
        });

        List<GenTableColumn> delColumns = tableColumns.stream().filter(column -> !dbTableColumnNames.contains(column.getColumnName())).collect(Collectors.toList());
        if (StringUtils.isNotEmpty(delColumns))
        {
            genTableColumnMapper.deleteGenTableColumns(delColumns);
        }
    }

    /**
     * 生成代码到zip
     */
    private void generatorCode(GenTable table, ZipOutputStream zip)
    {
        if (table == null) {
            throw new ServiceException("表信息不存在");
        }
        
        // 确保表字段信息被加载
        if (table.getColumns() == null || table.getColumns().isEmpty()) {
            List<GenTableColumn> columns = genTableColumnMapper.selectGenTableColumnListByTableId(table.getTableId());
            if (columns == null || columns.isEmpty()) {
                throw new ServiceException("表字段信息不存在");
            }
            table.setColumns(columns);
        }
        
        // 设置主子表信息
        setSubTable(table);
        // 设置主键列信息
        setPkColumn(table);

        VelocityInitializer.initVelocity();

        VelocityContext context = VelocityUtils.prepareContext(table);

        // 获取模板列表
        List<String> templates = VelocityUtils.getTemplateList(table.getTplCategory());
        for (String template : templates)
        {
            // 渲染模板
            StringWriter sw = new StringWriter();
            Template tpl = Velocity.getTemplate(template, Constants.UTF8);
            tpl.merge(context, sw);
            try
            {
                // 添加到zip
                zip.putNextEntry(new ZipEntry(VelocityUtils.getFileName(template, table)));
                IOUtils.write(sw.toString(), zip, Constants.UTF8);
                IOUtils.closeQuietly(sw);
                zip.flush();
                zip.closeEntry();
            }
            catch (IOException e)
            {
                log.error("渲染模板失败，表名：{}", table.getTableName(), e);
            }
        }
    }

    /**
     * 修改保存参数校验
     * 
     * @param genTable 业务信息
     */
    @Override
    public void validateEdit(GenTable genTable)
    {
        if (GenConstants.TPL_TREE.equals(genTable.getTplCategory()))
        {
            // 使用安全的方式处理参数
            Map<String, Object> paramsMap = new HashMap<>();
            Map<String, Object> originalParams = genTable.getParams();
            
            // 只保留需要的参数
            if (originalParams != null) {
                String[] allowedKeys = {
                    GenConstants.TREE_CODE,
                    GenConstants.TREE_PARENT_CODE,
                    GenConstants.TREE_NAME,
                    GenConstants.PARENT_MENU_ID,
                    GenConstants.PARENT_MENU_NAME,
                    "mergeMode" // 添加mergeMode参数
                };
                
                for (String key : allowedKeys) {
                    if (originalParams.containsKey(key)) {
                        Object value = originalParams.get(key);
                        // 确保值是基本类型或字符串，避免复杂对象序列化
                        if (value == null || value instanceof String || value instanceof Number || value instanceof Boolean) {
                            paramsMap.put(key, value);
                        } else {
                            paramsMap.put(key, value.toString());
                        }
                    }
                }
            }
            
            // 使用JSONObject确保生成合法的JSON格式
            String options = JSON.toJSONString(paramsMap);
            genTable.setOptions(options);
            
            String treeCode = paramsMap.getOrDefault(GenConstants.TREE_CODE, "").toString();
            String treeParentCode = paramsMap.getOrDefault(GenConstants.TREE_PARENT_CODE, "").toString();
            String treeName = paramsMap.getOrDefault(GenConstants.TREE_NAME, "").toString();

            if (StringUtils.isEmpty(treeCode))
            {
                throw new ServiceException("树编码字段不能为空");
            }
            else if (StringUtils.isEmpty(treeParentCode))
            {
                throw new ServiceException("树父编码字段不能为空");
            }
            else if (StringUtils.isEmpty(treeName))
            {
                throw new ServiceException("树名称字段不能为空");
            }
            else if (Objects.equals(treeCode, treeParentCode))
            {
                throw new ServiceException("树编码字段与树父编码字段不能相同");
            }
        }
        else if (GenConstants.TPL_SUB.equals(genTable.getTplCategory()))
        {
            if (StringUtils.isEmpty(genTable.getSubTableName()))
            {
                throw new ServiceException("关联子表的表名不能为空");
            }
            else if (StringUtils.isEmpty(genTable.getSubTableFkName()))
            {
                throw new ServiceException("子表关联的外键名不能为空");
            }
        }
    }

    /**
     * 设置主键列信息
     * 
     * @param table 业务表信息
     */
    public void setPkColumn(GenTable table)
    {
        if (table.getColumns() != null) {
            for (GenTableColumn column : table.getColumns())
            {
                if (column.isPk())
                {
                    table.setPkColumn(column);
                    break;
                }
            }
        }
        if (StringUtils.isNull(table.getPkColumn()))
        {
            if (table.getColumns() != null && !table.getColumns().isEmpty()) {
                table.setPkColumn(table.getColumns().get(0));
            }
        }
        if (GenConstants.TPL_SUB.equals(table.getTplCategory()))
        {
            if (table.getSubTable() != null && table.getSubTable().getColumns() != null) {
                for (GenTableColumn column : table.getSubTable().getColumns())
                {
                    if (column.isPk())
                    {
                        table.getSubTable().setPkColumn(column);
                        break;
                    }
                }
            }
            if (StringUtils.isNull(table.getSubTable().getPkColumn()))
            {
                if (table.getSubTable() != null && table.getSubTable().getColumns() != null && !table.getSubTable().getColumns().isEmpty()) {
                    table.getSubTable().setPkColumn(table.getSubTable().getColumns().get(0));
                }
            }
        }
    }

    /**
     * 设置主子表信息
     * 
     * @param table 业务表信息
     */
    public void setSubTable(GenTable table)
    {
        String subTableName = table.getSubTableName();
        if (StringUtils.isNotEmpty(subTableName))
        {
            table.setSubTable(genTableMapper.selectGenTableByName(subTableName));
        }
    }

    /**
     * 设置代码生成其他选项值
     * 
     * @param genTable 设置后的生成对象
     */
    public void setTableFromOptions(GenTable genTable)
    {
        if (genTable.getOptions() == null) {
            return;
        }
        
        JSONObject paramsObj = null;
        try {
            paramsObj = JSON.parseObject(genTable.getOptions());
        } catch (Exception e) {
            log.error("解析表信息options失败：", e);
            return;
        }
        
        if (StringUtils.isNotNull(paramsObj))
        {
            String treeCode = paramsObj.getString(GenConstants.TREE_CODE);
            String treeParentCode = paramsObj.getString(GenConstants.TREE_PARENT_CODE);
            String treeName = paramsObj.getString(GenConstants.TREE_NAME);
            String parentMenuId = paramsObj.getString(GenConstants.PARENT_MENU_ID);
            String parentMenuName = paramsObj.getString(GenConstants.PARENT_MENU_NAME);
            String mergeMode = paramsObj.getString("mergeMode");
            
            log.info("从options解析参数 - 上级菜单ID: {}, 上级菜单名称: {}", parentMenuId, parentMenuName);

            genTable.setTreeCode(treeCode);
            genTable.setTreeParentCode(treeParentCode);
            genTable.setTreeName(treeName);
            
            // 明确设置上级菜单ID和名称
            if (StringUtils.isNotEmpty(parentMenuId)) {
            genTable.setParentMenuId(parentMenuId);
            }
            
            if (StringUtils.isNotEmpty(parentMenuName)) {
            genTable.setParentMenuName(parentMenuName);
            }
            
            // 设置mergeMode，如果为空则默认为"1"（智能合并）
            if (StringUtils.isEmpty(mergeMode)) {
                mergeMode = "1";
            }
            genTable.setMergeMode(mergeMode);
            
            // 确保genTable.getParams()不为null
            if (genTable.getParams() == null) {
                genTable.setParams(new HashMap<>());
            }
            
            // 同时设置到params中，便于后续使用
            if (StringUtils.isNotEmpty(parentMenuId)) {
                genTable.getParams().put(GenConstants.PARENT_MENU_ID, parentMenuId);
            }
            
            if (StringUtils.isNotEmpty(parentMenuName)) {
                genTable.getParams().put(GenConstants.PARENT_MENU_NAME, parentMenuName);
            }
            
            genTable.getParams().put("mergeMode", mergeMode);
            
            log.info("设置表参数完成 - 上级菜单ID: {}, 上级菜单名称: {}, 合并模式: {}", 
                    genTable.getParentMenuId(), genTable.getParentMenuName(), genTable.getMergeMode());
        }
    }

    /**
     * 检查生成代码的文件是否已存在
     * 
     * @param tableName 表名称
     * @param genPath 生成路径
     * @return 存在的文件路径列表，如果没有文件存在则返回空列表
     */
    @Override
    public List<String> checkFilesExist(String tableName, String genPath) {
        // 查询表信息
        GenTable table = genTableMapper.selectGenTableByName(tableName);
        if (table == null) {
            throw new ServiceException("表信息不存在");
        }
        
        List<GenTableColumn> columns = genTableColumnMapper.selectGenTableColumnListByTableId(table.getTableId());
        if (columns == null || columns.isEmpty()) {
            throw new ServiceException("表字段信息不存在");
        }
        table.setColumns(columns);
        
        // 设置主子表信息
        setSubTable(table);
        // 设置主键列信息
        setPkColumn(table);

        // 如果传入了自定义路径，使用传入的路径
        if (StringUtils.isNotEmpty(genPath)) {
            log.info("使用传入生成路径: {}", genPath);
            // 替换掉table中的genPath
            table.setGenPath(genPath);
        }

        VelocityInitializer.initVelocity();
        
        // 获取模板列表
        List<String> templates = VelocityUtils.getTemplateList(table.getTplCategory());
        log.info("表[{}]模板列表: {}", tableName, templates);
        
        // 收集已存在的文件
        List<String> existingFiles = new ArrayList<>();
        for (String template : templates) {
            try {
                String path = VelocityUtils.getGenPath(table, template);
                log.info("检查文件是否存在: 模板={}, 路径={}", template, path);
                
                File file = new File(path);
                if (file.exists()) {
                    log.info("文件已存在: {}", path);
                    
                    // 检查是否是文件而不是目录
                    if (file.isFile()) {
                        existingFiles.add(path);
                    } else {
                        log.warn("路径存在但是是一个目录而不是文件: {}", path);
                    }
                } else {
                    log.info("文件不存在: {}", path);
                    
                    // 检查父目录是否存在
                    File parentDir = file.getParentFile();
                    if (parentDir != null && !parentDir.exists()) {
                        log.info("父目录不存在: {}", parentDir.getAbsolutePath());
                    }
                }
            } catch (Exception e) {
                log.error("检查文件是否存在时出错: {}", e.getMessage(), e);
            }
        }
        
        // 在日志中输出已存在的文件路径
        if (!existingFiles.isEmpty()) {
            log.info("表[{}]检查结果: 共{}个文件, 已存在{}个文件", 
                    tableName, templates.size(), existingFiles.size());
            
            // 限制日志输出的文件数量，避免日志过长
            int logLimit = Math.min(existingFiles.size(), 5);
            StringBuilder sb = new StringBuilder("已存在的文件包括: ");
            for (int i = 0; i < logLimit; i++) {
                sb.append("\n  ").append(existingFiles.get(i));
            }
            if (existingFiles.size() > logLimit) {
                sb.append("\n  ... 以及其他 ").append(existingFiles.size() - logLimit).append(" 个文件");
            }
            log.info(sb.toString());
        } else {
            log.info("表[{}]检查结果: 共{}个文件, 没有发现已存在的文件", tableName, templates.size());
        }
        
        return existingFiles;
    }

    /**
     * 获取表结构SQL
     * 
     * @param tableName 表名称
     * @return 表结构SQL
     */
    @Override
    public String getTableSql(String tableName) {
        if (StringUtils.isEmpty(tableName)) {
            log.error("获取表结构SQL错误：表名为空");
            throw new ServiceException("表名不能为空");
        }
        
        try {
            log.info("开始获取表[{}]的结构SQL", tableName);
            
            // 检查jdbcTemplate是否为null
            if (jdbcTemplate == null) {
                log.error("获取表结构SQL错误：jdbcTemplate未注入");
                return "错误：数据库连接未初始化";
            }
            
            // 查询表结构创建SQL
            String showCreateSql = "SHOW CREATE TABLE " + tableName;
            log.info("执行SQL: {}", showCreateSql);
            
            Map<String, Object> result = jdbcTemplate.queryForMap(showCreateSql);
            log.info("查询结果键集合: {}", result.keySet());
            log.info("查询结果完整内容: {}", result);
            
            // 结果集中CREATE TABLE语句对应的键可能是"Create Table"或"CREATE TABLE"
            String createTableSql = "";
            if (result.containsKey("Create Table")) {
                log.info("找到键 'Create Table'");
                createTableSql = (String) result.get("Create Table");
                log.info("Create Table值: {}", createTableSql);
            } else if (result.containsKey("CREATE TABLE")) {
                log.info("找到键 'CREATE TABLE'");
                createTableSql = (String) result.get("CREATE TABLE");
                log.info("CREATE TABLE值: {}", createTableSql);
            } else {
                // 遍历寻找包含CREATE TABLE的键
                log.info("未找到标准键，开始遍历所有键");
                for (Map.Entry<String, Object> entry : result.entrySet()) {
                    log.info("检查键: '{}', 值类型: {}, 值内容: {}", 
                            entry.getKey(), 
                            entry.getValue() != null ? entry.getValue().getClass().getName() : "null",
                            entry.getValue());
                    
                    if (entry.getKey().toUpperCase().contains("CREATE") && entry.getValue() instanceof String) {
                        createTableSql = (String) entry.getValue();
                        log.info("找到匹配键: '{}'，值: {}", entry.getKey(), createTableSql);
                        break;
                    }
                }
            }
            
            if (StringUtils.isEmpty(createTableSql)) {
                // 如果找不到CREATE TABLE语句，返回整个结果集的字符串表示
                log.warn("无法从结果中提取CREATE TABLE语句，返回完整结果");
                createTableSql = result.toString();
                log.info("返回完整结果: {}", createTableSql);
            }
            
            log.info("成功获取表[{}]的结构SQL，长度: {}, 内容: {}", tableName, createTableSql.length(), createTableSql);
            return createTableSql;
        } catch (Exception e) {
            log.error("获取表结构SQL出错：", e);
            throw new ServiceException("获取表结构SQL出错: " + e.getMessage());
        }
    }
}
